package net.vinote.smart.platform.service.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 增强系统安全性
 * 
 * @author 郑俊伟
 * 
 */
public class SecurityFilter implements Filter {

	private List<Pattern> securityRegexList;
	private static final String[] SECURITY_REGEX = { ".*<.*script.*",
			".*<.*img.*", ".*<.*a.*", ".*<.*ifrmae.*" };

	public void init(FilterConfig filterConfig) throws ServletException {

		securityRegexList = new ArrayList<Pattern>();
		for (String regex : SECURITY_REGEX) {
			securityRegexList.add(Pattern.compile(regex,
					Pattern.CASE_INSENSITIVE));
			try {
				securityRegexList.add(Pattern.compile(
						URLEncoder.encode(regex, "utf-8"),
						Pattern.CASE_INSENSITIVE));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}

	}

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		// 请求类型检查
		String reqMethod = request.getMethod();
		if (!"GET".equalsIgnoreCase(reqMethod)
				&& !"POST".equalsIgnoreCase(reqMethod)) {
			response.sendError(515, "无效请求类型:" + reqMethod);
			return;
		}
		// 请求头是否包含非法内容
		String queryStr = request.getQueryString();
		if (queryStr != null) {
			for (Pattern p : securityRegexList) {
				if (p.matcher(queryStr).matches()) {
					response.sendError(403, "无效请求参数:" + queryStr);
					return;
				}
			}
		}

		String preUrl = request.getHeader("Referer");
		if (preUrl != null && preUrl.indexOf(request.getContextPath()) == -1) {
			response.sendError(515, "存在夸张请求风险:" + preUrl);
			return;
		}
		chain.doFilter(request, response);
	}

	public void destroy() {

	}

}
